# -*- coding: utf-8 -*-
'''
Repository scanner for mercurial.
'''
from processors.mercurial_repo_processor import \
    PullableMercurialRepoProcessor, LocalMercurialRepoProcessor
import os
import logging
from processors.repository_scanner import RepositoryScanner, execute_processing
from mercurial import ui, hg
from urlparse import urlparse

class MercurialRepoScanner(RepositoryScanner): #pylint: disable-msg=R0903
    """
    Scanner for mercurial repositories.
    
    It looks through subdirectories and finds all subdirectories which
    are actually mercurial repositories.
    """

    def _add_mercurial_repository(self, processors, conf):
        """
        Adds mercurial repository with configuration to list of processors.
        """
        logging.info("Processing " + conf['location'])
        if conf['pullurl'] is not None:
            processor = PullableMercurialRepoProcessor(self._settings, \
                                self._storepath, self._oldpath, conf)
            processor.initialize()
            logging.info("Pulling " + conf['location'])
            output = processor.pull()
            logging.debug("Pull returned " + str(output))
        else:
            processor = LocalMercurialRepoProcessor(self._settings, \
                                self._storepath, self._oldpath, conf)
            processor.initialize()
        execute_processing(processors, conf, processor)      

    def _scan_directories(self, processors, conf, basepath):
        logging.info("Scanning " + basepath)
        for entry in os.walk(basepath): 
            root = entry[0]
            dirs = entry[1]
            i = 0
            while i < len(dirs):
                if dirs[i] == ".hg":
                    dirs[:] = []
                    subdirectory = root[len(basepath):]
                    title = conf['title'] \
                        if subdirectory == "" else subdirectory 
                    pullurl = conf['pullurl'] if 'pullurl' in conf else None
                    subpullurl = None if pullurl is None \
                        else pullurl + \
                            subdirectory.replace("\\", "/")
                    logging.info("Adding " + subdirectory)
                    subweburl = conf['weburl'] + \
                        subdirectory.replace("\\", "/")
                    new_conf = {}
                    new_conf.update(conf)
                    new_conf['weburl'] = subweburl
                    new_conf['pullurl'] = subpullurl
                    new_conf['title'] = title
                    new_conf['location'] = root
                    self._add_mercurial_repository(processors, new_conf)
                elif dirs[i].startswith("."):
                    del dirs[i]
                else:
                    i = i + 1

    def _clone_repository(self, conf):
        """
        Clones the repository when it does not exist.
        """
        if not 'pullurl' in conf:
            raise Exception('pullurl not defined '
                'and repository is not created ' + conf['location'])
        src = conf['pullurl']
        dst = conf['location']
        dstpath = urlparse(dst).path
        logging.info("Cloning repository from " + src + " to " + dstpath)        
        the_ui = ui.ui()
        peeropts = {}
        hg.clone(the_ui,peeropts, src,dst)
        
    def scan_repo(self, processors, conf):
        """
        Scans repository in specified location.
        Might be more than one in case of file based
        repository and repositories inside subdirectories.
        """
        location = conf['location']
        if location.startswith("file://"):
            basepath = location[len("file://"):]
        else:
            basepath = location
        if basepath[-1] == "\\":
            basepath = basepath[:-1]
        updir = os.path.split(basepath)[0]
        if not os.path.exists(basepath) and \
                os.path.exists(updir) and os.path.isdir(updir):
            self._clone_repository(conf)
        self._scan_directories(processors, conf, basepath)
